<?php

namespace App\Models\System;

use App\Enum\Models\System\Menu\Status;
use App\Enum\Models\System\Menu\Type;
use App\Models\BaseModel;
use Illuminate\Database\Eloquent\Collection;

class Menu extends BaseModel
{
    /**
     * 允许批量更新字段
     */
    protected $fillable = [
        'path',
        'title',
        'name',
        'code',
        'component',
        'type',
        'status',
        'p_id',
        'sort',
        'meta',
    ];

    /**
     * 属性默认值
     */
    protected $attributes = [
        'p_id' => 0,
        'status' => Status::Normal->value,
        'type' => Type::Menu->value,
    ];

    /**
     * @return array<string, string>
     */
    protected function casts(): array
    {
        return [
            'created_at' => 'datetime:Y-m-d H:i:s',
            'updated_at' => 'datetime:Y-m-d H:i:s',
            'meta' => 'json',
        ];
    }

    /**
     * 下级
     */
    public function childs()
    {
        return $this->hasMany(self::class, 'p_id', 'id');
    }

    /**
     * 加载下级 类型为菜单 状态为正常的
     */
    public function children()
    {
        return $this->childs()->with(['children' => function ($query) {
            $query->where('type', Type::Menu)->where('status', Status::Normal);
        }]);
    }

    /**
     * 保存树形结构的权限字段同数据库字段 children为子数据字段
     */
    public static function createTree(array $data, $pid = 0)
    {
        foreach ($data as $item) {
            $item['p_id'] = $pid;
            $row = self::create($item);
            if (isset($item['children']) && ! empty($item['children'])) {
                self::createTree($item['children'], $row->id);
            }
        }
    }

    /**
     * 获取菜单 如果传入了用户 根据用户查找
     */
    public static function getMenusByAdmin(?Admin $admin = null)
    {
        $query = self::query();
        if ($admin && ! $admin->is_super_admin) {
            $query->leftJoin('permission_role', 'permission_role.permission_id', '=', 'menus.id')
                ->leftJoin('admin_role', 'admin_role.role_id', '=', 'permission_role.role_id')
                ->leftJoin('admins', 'admins.id', '=', 'admin_role.admin_id')
                ->where('admins.id', $admin->id);
        }

        $list = $query
            ->whereIn('menus.type', [Type::Menu, Type::Catalog, Type::Embedded, Type::Link])
            ->where('menus.status', Status::Normal)
            ->orderBy('menus.sort', 'desc')
            ->orderBy('menus.id', 'asc')
            ->select('menus.*')
            ->get();

        return self::buildTree($list);
    }

    /**
     * 构建树形
     */
    public static function buildTree(Collection $list, $p_id = 0)
    {
        return $list->filter(function ($item) use ($p_id) {
            return $item->p_id == $p_id;
        })->map(function ($item) use ($list) {
            $item['children'] = self::buildTree($list, $item->id);

            return $item;
        });
    }
}
